﻿#include "../include/alphadog_monitor/graphplot.h"
#include "ui_graphplot.h"
#include <QDebug>
#include <math.h>
namespace alphadog_monitor{

GraphThread::GraphThread(int iCount, QList<QCustomPlot*>* list, std::vector<std::vector<QDoubleSpinBox*>>* _scales, QNode* _node):
    m_iThreadCount(iCount), graphs(list), scales(_scales), qnode(_node){
    // 初始化曲线数据
    for(int i = 0; i < 4; i ++){
        std::vector<QList<PointType>>* graph_type = new std::vector<QList<PointType>>();
        graph_container.push_back(*graph_type);
        for(int j = 0; j < 3; j ++){
            QList<PointType>* data = new QList<PointType>();
            graph_container[i].push_back(*data);
        }
    }

    // 关联信号和表格
    connect(qnode, SIGNAL(updateGraph(float*, QString*)), this, SLOT(slot_updateGraphData(float*, QString*)));
}


GraphThread::~GraphThread()
{
    for(int i = 0; i < m_iThreadCount; i++)
    {
        m_threadList.value(i)->quit();
        m_threadList.value(i)->wait();
        m_qTimerList.value(i)->deleteLater();
        m_threadList.value(i)->deleteLater();
    }
}

void GraphThread::createItem()
{
    for(int i = 0;i < m_iThreadCount;i++)
    {
        QTimer *timer = new QTimer();
        QThread  *thread = new QThread();
        m_qTimerList.append(timer);
        m_threadList.append(thread);
    }
}

void GraphThread::startMultThread(int dt = 5)
{
    // 设置图表更新时间间隔
    dtGraph = dt;

    for(int i = 0; i < m_qTimerList.size(); i++)
    {
        m_qTimerList.value(i)->start(dtGraph);
        m_qTimerList.value(i)->moveToThread(m_threadList.value(i));
        switch(i){
            case 0: QObject::connect(m_qTimerList.value(i),SIGNAL(timeout()),this,SLOT(realtimeGraph1()),Qt::DirectConnection); break;
            case 1: QObject::connect(m_qTimerList.value(i),SIGNAL(timeout()),this,SLOT(realtimeGraph2()),Qt::DirectConnection); break;
            case 2: QObject::connect(m_qTimerList.value(i),SIGNAL(timeout()),this,SLOT(realtimeGraph3()),Qt::DirectConnection); break;
            case 3: QObject::connect(m_qTimerList.value(i),SIGNAL(timeout()),this,SLOT(realtimeGraph4()),Qt::DirectConnection); break;
        }
        m_threadList.value(i)->start();
    }
}

/**
 * @brief 更新曲线图内部数据及样式
 * @param _graph
 */
void GraphThread::updateGraphForm(int type){
    if(enabled[type]){
        QCustomPlot* graph = graphs->operator [](type);
        // 获取当前时间
        double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
        if(Timer_firstRun){
            Timer_startTime = key;
            key = 0;
            Timer_firstRun = 0;
        }
        else{
            key = (key - Timer_startTime);
        }
        graph->xAxis->setRange(key, 5, Qt::AlignRight);

        // 对三条曲线分别设置
        rwlocker.lockForRead();
        for(int i = 0; i < 3; i ++){
            if(!graph_container[type][i].empty()){
                for(int s = 0; s < graph_container[type][i].size(); s ++){
                    try{
                        PointType p = graph_container[type][i].at(s);
                        graph->graph(i)->addData(p.stamp, p.value * scales->at(type)[i]->value());
                        if(graph->graph(i)->name()!= p.name){
                            graph->graph(i)->setName(p.name);
                        }
                    }
                    catch(int){}
                }
            }
            setClearFlag(type, true);
            graph->graph(i)->data()->removeBefore(key-5);
            graph->graph(i)->rescaleValueAxis(true);
        }
        rwlocker.unlock();
        emit plotGraph(type);
    }
}

/**
 * @brief 更新曲线的数据
 */
void GraphThread::slot_updateGraphData(float* value, QString* name){
    // 获取当前时间
    double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
    if(Timer_firstRun){
        Timer_startTime = key;
        Timer_firstRun = 0;
    }

    // 上写锁，更新曲线的存储数据
    rwlocker.lockForWrite();
    for(int i = 0; i < 4; i ++){
        if(clearflag[i]){
            for(int j = 0; j < 3; j ++){
                if(!graph_container[i][j].empty())
                graph_container[i][j].clear();
            }
        }
        setClearFlag(i,false);
    }

    PointType p;
    p.stamp = key-Timer_startTime;
    for(int i = 0; i < 4; i ++){
        for(int j = 0; j < 3; j ++){
            if(graph_container[i][j].size() > 100) graph_container[i][j].clear();
            else{
                p.name = name[i*3 + j];
                p.value = value[i*3 + j];
                graph_container[i][j].append(p);
            }

        }
    }
    rwlocker.unlock();
}

graphplot::graphplot(QWidget *parent, QNode* _node) :
    QDialog(parent),
    ui(new Ui::graphplot),
    _parent(parent)
{
    ui->setupUi(this);

    // 创建设置窗口
    setinf = new graph_setting(this);
    this->setWindowFlags(Qt::Dialog|Qt::FramelessWindowHint);

    // 创建调试曲线
    params_tune = new paramstuning_window(this, _node);

    // 初始化图表
    graphList.append(new QCustomPlot(ui->graph1_plot));
    graphList.append(new QCustomPlot(ui->graph2_plot));
    graphList.append(new QCustomPlot(ui->graph3_plot));
    graphList.append(new QCustomPlot(ui->graph4_plot));

    // 创建图表线程
    graph_threads = new GraphThread(4, &graphList, &graph_scales, _node);

    // 初始化
    initWidget();
}

graphplot::~graphplot()
{
    delete ui;
}

void graphplot::initWidget(void){
    for(int i = 0; i < graphList.size(); i ++){
        QCustomPlot* graph = graphList[i];
        // 设置显示区域大小
        graph->resize(920, 140);

        // 添加三条曲线
        for(int i = 0; i < 3; i ++){
            graph->addGraph();
            switch(i){
                case 0: graph->graph(i)->setPen(QPen(Qt::red)); graph->graph(i)->setName("data1"); break;
                case 1: graph->graph(i)->setPen(QPen(Qt::blue)); graph->graph(i)->setName("data2"); break;
                case 2: graph->graph(i)->setPen(QPen(Qt::green)); graph->graph(i)->setName("data3"); break;
            }
        }

        // 设置曲线属性可视化
        graph->legend->setVisible(false);
        graph->yAxis->setVisible(true);
        graph->xAxis->setVisible(true);

        // 设置鼠标控制属性
        graph->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
        graph->axisRect()->setRangeZoom(Qt::Vertical);
    }

    // 初始化check_box
    std::vector<QCheckBox*>* box;
    for(int i = 0; i < 4; i ++){
        box = new std::vector<QCheckBox*>();
        graph_checkboxes.push_back(*box);
    }
    graph_checkboxes[0].push_back(ui->graph1_data1);
    graph_checkboxes[0].push_back(ui->graph1_data2);
    graph_checkboxes[0].push_back(ui->graph1_data3);

    graph_checkboxes[1].push_back(ui->graph2_data1);
    graph_checkboxes[1].push_back(ui->graph2_data2);
    graph_checkboxes[1].push_back(ui->graph2_data3);

    graph_checkboxes[2].push_back(ui->graph3_data1);
    graph_checkboxes[2].push_back(ui->graph3_data2);
    graph_checkboxes[2].push_back(ui->graph3_data3);

    graph_checkboxes[3].push_back(ui->graph4_data1);
    graph_checkboxes[3].push_back(ui->graph4_data2);
    graph_checkboxes[3].push_back(ui->graph4_data3);
    for(int i = 0; i < 4; i ++){
        for(int j = 0; j < 3; j ++){
            graph_checkboxes[i][j]->setChecked(true);
        }
    }

    // 初始化scales
    std::vector<QDoubleSpinBox*>* num;
    for(int i = 0; i < 4; i ++){
        num = new std::vector<QDoubleSpinBox*>();
        graph_scales.push_back(*num);
    }
    graph_scales[0].push_back(ui->graph1_scale1);
    graph_scales[0].push_back(ui->graph1_scale2);
    graph_scales[0].push_back(ui->graph1_scale3);

    graph_scales[1].push_back(ui->graph2_scale1);
    graph_scales[1].push_back(ui->graph2_scale2);
    graph_scales[1].push_back(ui->graph2_scale3);

    graph_scales[2].push_back(ui->graph3_scale1);
    graph_scales[2].push_back(ui->graph3_scale2);
    graph_scales[2].push_back(ui->graph3_scale3);

    graph_scales[3].push_back(ui->graph4_scale1);
    graph_scales[3].push_back(ui->graph4_scale2);
    graph_scales[3].push_back(ui->graph4_scale3);
    for(int i = 0; i < 4; i ++){
        for(int j = 0; j < 3; j ++){
            graph_scales[i][j]->setValue(1);
        }
    }

    // 初始化定时器线程
    graph_threads->createItem();
    graph_threads->startMultThread(25);
    QObject::connect(graph_threads, SIGNAL(plotGraph(int)), this, SLOT(slot_plotGraph(int)));

    // 设置按键
    connect(ui->Btn_Setting,&QPushButton::clicked,[=](){
      setinf->show();
    });

    // 最小化和关闭
    connect(ui->btnWinClose, &QPushButton::clicked, [=]() {
        this->close();
    });
    connect(ui->btnWinMin, &QPushButton::clicked, [=]() { this->showMinimized(); });

    // 设置
    connect(ui->Btn_Setting, &QPushButton::clicked, [=]() { setinf->show(); });

    // 调试
    connect(ui->Btn_Test, &QPushButton::clicked, [=]() { params_tune->show(); });

    // 启动按键
    connect(ui->graph1_enable,&QPushButton::clicked,[=](){enableGraph(ui->graph1_enable, 0);});
    connect(ui->graph2_enable,&QPushButton::clicked,[=](){enableGraph(ui->graph2_enable, 1);});
    connect(ui->graph3_enable,&QPushButton::clicked,[=](){enableGraph(ui->graph3_enable, 2);});
    connect(ui->graph4_enable,&QPushButton::clicked,[=](){enableGraph(ui->graph4_enable, 3);});
    connect(ui->graphs_enable,&QPushButton::clicked,[=](){
        if(!enabled[0]) enableGraph(ui->graph1_enable, 0);
        if(!enabled[1]) enableGraph(ui->graph2_enable, 1);
        if(!enabled[2]) enableGraph(ui->graph3_enable, 2);
        if(!enabled[3]) enableGraph(ui->graph4_enable, 3);
    });
    connect(ui->graphs_disable,&QPushButton::clicked,[=](){
        if(enabled[0]) enableGraph(ui->graph1_enable, 0);
        if(enabled[1]) enableGraph(ui->graph2_enable, 1);
        if(enabled[2]) enableGraph(ui->graph3_enable, 2);
        if(enabled[3]) enableGraph(ui->graph4_enable, 3);
    });
}

void graphplot::enableGraph(QPushButton* btn, int index){
    if(btn->text() == "启动"){
        enabled[index] = true;
        btn->setText("暂停");
        btn->setStyleSheet("border:2px groove gray;border-radius:10px;padding:2px 4px;background-color:rgba(255, 0, 0,64);");
        graph_threads->enabled[index] = true;
    }
    else{
        enabled[index] = false;
        btn->setText("启动");
        btn->setStyleSheet("border:2px groove gray;border-radius:10px;padding:2px 4px;background-color:rgba(0, 255, 0,64);");
        graph_threads->enabled[index] = false;
    }

}

/**
 * @brief 更新绘制曲线
 * @param id
 * @return
 */
void graphplot::slot_plotGraph(int id){
    if(enabled[id]){
        for(int i = 0; i < 3; i ++){
            graph_checkboxes[id][i]->setText(graphList.at(id)->graph(i)->name());
            if(!graph_checkboxes[id][i]->isChecked()) graphList.operator [](id)->graph(i)->setVisible(false);
            else graphList.operator [](id)->graph(i)->setVisible(true);
        }
        graphList.operator [](id)->replot();
    }
}

void graphplot::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        QPoint startPos = event->globalPos();
        m_offPos = startPos - geometry().topLeft();
    }
    QDialog::mousePressEvent(event);
}

void graphplot::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() == Qt::LeftButton) {
        QPoint endPos = event->globalPos();
        move(endPos - m_offPos);
    }
    QDialog::mouseMoveEvent(event);
}

void graphplot::mouseReleaseEvent(QMouseEvent *event)
{
    QDialog::mouseReleaseEvent(event);
}


}

